/**
 * Created with IntelliJ IDEA.
 * User: aleksandr
 * Date: 29.06.13
 */
package com.google.code.bankagregator.adapter.bank.aval.parsers.deposits;

import com.google.code.bankagregator.adapter.exception.AdapterException;
import com.google.code.bankagregator.adapter.exception.AdapterRecognizeDataException;
import com.google.code.bankagregator.entities.Bank;
import com.google.code.bankagregator.entities.Deposit;
import org.joda.time.Period;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

abstract class AbstractAvalDeposit {

    private final String BANK_TITLE = "АО «Райффайзен Банк Аваль»";
    private final String SITE_URL = "http://www.aval.ua";

    protected int DEPOSIT_UAH = 0;
    protected int DEPOSIT_UAH_TERMS = 1;
    protected int DEPOSIT_UAH_LESS_100K = 2;
    protected int DEPOSIT_UAH_MORE_100K = 3;

    protected int DEPOSIT_USD = 0;
    protected int DEPOSIT_USD_TERMS = 5;
    protected int DEPOSIT_USD_LESS_10K = 6;
    protected int DEPOSIT_USD_MORE_10K = 7;

    protected int DEPOSIT_EUR = 0;
    protected int DEPOSIT_EUR_TERMS = 9;
    protected int DEPOSIT_EUR_LESS_4K = 10;
    protected int DEPOSIT_EUR_4K_8K = 11;
    protected int DEPOSIT_EUR_8K_16K = 12;
    protected int DEPOSIT_EUR_16K_40K = 13;
    protected int DEPOSIT_EUR_MORE_40K = 14;

    private String productURL = null;
    private Bank bank = null;

    /**
     * @param url string URL of specified product page
     */
    public AbstractAvalDeposit(String url) {
        bank = new Bank();
        bank.setName(BANK_TITLE);
        bank.setUrl(SITE_URL);
        productURL = url;
    }

    /**
     * @return string URL of current product page
     */
    public String getDepositPageURL() {
        return productURL;
    }

    /**
     * @return Bank VO with data for current product
     */
    public Bank getBank() {
        return bank;
    }

    /**
     * Parses string for time period
     *
     * @param term alternative date format, like "3 days" or "7 months"
     * @return int number of days
     * @throws com.google.code.bankagregator.adapter.exception.AdapterRecognizeDataException
     *
     */
    public int parsePeriod(String term) throws AdapterRecognizeDataException {
        if (term.contains("days")) {
            PeriodFormatter periodFormatter = new PeriodFormatterBuilder()
                    .minimumPrintedDigits(1)
                    .appendDays()
                    .appendSuffix("days", " days")
                    .toFormatter();
            Period period = periodFormatter.parsePeriod(term);
            return period.getDays();

        } else if (term.contains("months")) {
            PeriodFormatter periodFormatter = new PeriodFormatterBuilder()
                    .minimumPrintedDigits(1)
                    .appendMonths()
                    .appendSuffix("months", " months")
                    .toFormatter();
            Period period = periodFormatter.parsePeriod(term);
            return period.getMonths() * 31;
        } else {
            throw new AdapterRecognizeDataException("Unsupported date format");
        }

    }

    public Map<String, Integer> normalizeTerms(Elements termsElements) throws AdapterRecognizeDataException {
        Map<String, Integer> termsMap = new HashMap<>();
        for (int i = 1; i < termsElements.size(); i++) {
            Element termElement = termsElements.get(i);
            String termTitle = termElement.text();
            String term = termTitle;

            term = term.replaceAll("\\u00a0", " ");
            term = term.replace("день", "days");
            term = term.replace("дней", "days");
            term = term.replace("месяца", "months");
            term = term.replace("месяцев", "months");

            int days = parsePeriod(term);
            termsMap.put(termTitle, days);
        }
        return termsMap;
    }

    abstract public List<Deposit> getDeposits() throws AdapterException;
}
